
#include <BFont>
#include <BPainter>
#include <BActiveEvent>
#include <BFocusEvent>
#include <BMouseEvent>
#include <BKeyEvent>
#include <BScrollBar>

#include "IComboBoard.h"
#include "member_BComboBox.h"

using namespace BWE;

IComboBoard::IComboBoard(member_BComboBox& com_member, BComboBox* parent) : member(com_member), BScrollArea(parent)
{
	combox = parent;
	hoveredIndex = -1;
	pressedIndex = -1;
	dirty = true;
}
IComboBoard::~IComboBoard()
{

}

void IComboBoard::freshItemRects()
{
	const BFont* font = this->font();
	if (!font)
		return;
	int cx = this->clientRect().x();
	int cy = this->clientRect().y();
	int cw = this->clientRect().width();
	int ch = this->clientRect().height();

	int posY = cy;
	for (int i = 0; i < member.items.size(); i++)
	{
		ComboItem& item = member.items[i];
		item.rect.set(cx, posY, cw, member.rowHeight);
		item.iconRect = item.rect.align(member.align, member.iconSize);
		item.textSize = font->textSize(item.text);
		BRect textArea = item.rect;
		if (member.align & Align_Left)
			textArea.left() = item.iconRect.right() + member.space;
		if (member.align & Align_Right)
			textArea.right() = item.iconRect.left() - member.space;
		item.textRect = textArea.align(member.align, item.textSize);
		posY += member.rowHeight;
	}
	totalSize.set(cw, posY);
	BRect area(this->clientRect().pos(), totalSize);
	this->setArea(area);
	this->verticalScrollBar()->setStep(member.rowHeight);
}

void IComboBoard::scrollArea()
{
	showBegin = -1;
	showCount = 0;
	BRect crect = this->clientRect();
	BPoint offset = this->offset();
	for (int i = 0; i < member.items.size(); i++)
	{
		ComboItem& item = member.items[i];
		BRect rect = item.rect + offset;
		if (rect.intersect(crect))
		{
			if (showBegin < 0)
			{
				showBegin = i;
			}
			else
			{
				showCount++;
			}
		}
		else
		{
			if (showCount > 0)
				break;
		}
	}
	this->fresh();
}

void IComboBoard::showEvent(const BEvent& showEvent)
{
	int x = 0;
	int y = combox->height();
	int w = combox->width();
	int h = (member.rowHeight + 1) * member.items.size() + this->shellSize().height() ;
	BPoint abPos = this->absolutePos();
	int rootHeight = this->root()->height();
	int maxHeight = rootHeight - abPos.y();
	if (h > maxHeight)
		h = maxHeight;
	this->setRect(x, y, w, h);
}
void IComboBoard::hideEvent(const BEvent& event)
{
	hoveredIndex = -1;
}

void IComboBoard::styleEvent(const BEvent& event)
{
	dirty = true;
}
void IComboBoard::freshEvent(const BEvent& event)
{
	if (dirty)
	{
		freshItemRects();
		dirty = false;
	}
}
void IComboBoard::paintEvent(const BEvent& event)
{
	BWidget::paintEvent(event);

	int width = this->width();
	int height = this->height();
	BPoint offset = this->offset();

	BPainter painter(this);

	for(int i = 0; i < showCount; i++)
	{
		int index = showBegin + i;
		ComboItem& item = member.items[index];
		BRect rect = item.rect + offset;
		BRect iconRect = item.iconRect + offset;
		BRect textRect = item.textRect + offset;

		State state = State_Normal;
		if (combox_member(combox)->current == index)
		{
			painter.setColor(Color_Item_Selected);
			painter.fillRect(rect);
			painter.setColor(Value_Border);
			painter.drawRect(rect);
			state = State_Pressed;
		}
		if(hoveredIndex == index)
		{
			painter.setColor(Color_Item_Hovered);
			painter.fillRect(rect);
			painter.setColor(Value_Border);
			painter.drawRect(rect);
			state = State_Hovered;
		}
		if (item.icon)
		{
			painter.drawImage(iconRect, item.icon->image(state));
		}
		painter.setColor(Color_Text);
		painter.drawText(textRect, item.text);
	}
}

void IComboBoard::activeEvent(const BActiveEvent& activeEvent)
{
	if (activeEvent.active() == Active_On)
	{

	}
	if (activeEvent.active() == Active_Off)
	{
		this->hide();
	}
}
void IComboBoard::focusEvent(const BFocusEvent& focusEvent)
{

}

void IComboBoard::keyDownEvent(const BKeyEvent& keyEvent)
{
	if (keyEvent.key() == Key_Enter)
	{
		combox->setCurrent(hoveredIndex);
		this->hide();
		return;
	}

	int index = hoveredIndex;
	if(keyEvent.key() == Key_Up)
		index--;
	if(keyEvent.key() == Key_Down)
		index++;
	member.items.correct(index);
	if (hoveredIndex != index)
	{
		hoveredIndex = index;
		fresh();
	}
}

void IComboBoard::mouseEnterEvent(const BMouseEvent& mouseEvent)
{
	pressedIndex = -1;
	hoveredIndex = -1;
}
void IComboBoard::mouseLeaveEvent(const BMouseEvent& mouseEvent)
{
	pressedIndex = -1;
	hoveredIndex = -1;
}

void IComboBoard::mouseClickEvent(const BMouseEvent& mouseEvent)
{
	if (hoveredIndex >= 0)
	{
		combox->setCurrent(hoveredIndex);
		combox->emit(Signal_CurrentSelected, hoveredIndex);
		this->hide();
	}

}
void IComboBoard::mouseMoveEvent(const BMouseEvent& mouseEvent)
{
	const BPoint& pos = mouseEvent.pos();
	BPoint offset = this->offset();
	for (int i = 0; i < showCount; i++)
	{
		int index = showBegin + i;
		ComboItem& item = member.items[index];
		BRect rect = item.rect + offset;
		if (rect.contain(pos))
		{
			if (hoveredIndex != index)
			{
				hoveredIndex = index;
				combox->emit(Signal_ItemHovered, hoveredIndex);
				fresh();
			}
			break;
		}
	}
}
